package net.wofly.right.shiro;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import net.wofly.common.util.CryptUserUtil;
import net.wofly.right.domain.FuncList;
import net.wofly.right.domain.Role;
import net.wofly.right.domain.User;
import net.wofly.right.service.IRightConfigService;
import net.wofly.right.service.IUserRoleService;
import net.wofly.right.service.IUserService;

/**
 * shiro身份校验核心类
 * <p>
 * 2017年11月1日
 */

public class MyShiroRealm4Employee extends AuthorizingRealm {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private IUserService iUserService;

    @Autowired
    private IUserRoleService iUserRoleService;

    @Autowired
    private IRightConfigService iRightConfigService;

    /**
     * 认证信息.(身份验证) : Authentication 是用来验证用户身份
     *
     * @param authcToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
            throws AuthenticationException {
        logger.info(">>> 进入【User】身份认证方法：MyShiroRealm4User.doGetAuthorizationInfo()");
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        String name = token.getUsername();
        String password = String.valueOf(token.getPassword());
        //密码进行加密处理  明文为  password+name
        String paw = password + name;
        //String pawDES = MyDES.encryptBasedDes(paw);
        String pawDES = CryptUserUtil.generatePassword(paw);
        User user = null;
        // 从数据库获取对应用户名密码的用户
        user = iUserService.findByMobileAndPassword(name, password);
        if (null == user) {
            throw new AccountException("帐号或密码不正确！");
        } else if ("0".equals(user.getStatus())) {
            /**
             * 如果用户的status为禁用。那么就抛出<code>DisabledAccountException</code>
             */
            throw new DisabledAccountException("此帐号已经设置为禁止登录！");
        } else {
            setSession(user.getUserID(),user);
            //登录成功
        }
        logger.info(">>>【User】身份认证成功，登录用户：" + name);
        return new SimpleAuthenticationInfo(user, password, getName());
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        logger.info(">>> 进入【User】权限认证方法：MyShiroRealm4User.doGetAuthorizationInfo()");
        if (principals.getPrimaryPrincipal() instanceof User) {
            User user = (User) SecurityUtils.getSubject().getPrincipal();
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            Set<String> roleSet = new HashSet<String>();
            Set<String> permissionSet = new HashSet<String>();
            //根据用户ID查询角色（role），放入到Authorization里。
            //角色信息、 权限信息
            List<Role> roles = iUserRoleService.findRolesByUserID(user.getUserID());
            for (Role role : roles) {
                roleSet.add(role.getRoleName());
                List<FuncList> funcLists = iRightConfigService.findFuncListByRoleID(role.getRoleID());
                for (FuncList funcList : funcLists) {
                    permissionSet.add(funcList.getFuncUrl());
                }
            }
            info.setRoles(roleSet);
            info.setStringPermissions(permissionSet);
            logger.info(">>> 结束【User】权限认证方法：MyShiroRealm4User.doGetAuthorizationInfo()");
            return info;
        }
        return null;
    }

    /**
     * 将一些数据放到ShiroSession中,以便于其它地方使用
     * <p>
     * 比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到
     */
    private void setSession(Object key, Object value) {
        Subject subject = SecurityUtils.getSubject();
        if (null != subject) {
            Session session = subject.getSession();
            logger.info(">>>Session默认超时时间为[" + session.getTimeout() + "]毫秒");
            if (null != session) {
                session.setAttribute(key, value);
            }
        }
    }

}
